#include "main.h"
#include "simI2c.h"
#include "usart.h"
#include "hmc5883.h"
#include <stdio.h>
#include "delay.h"
// 微秒级延时函数（基于SysTick）

void simI2cStart(void)
{
    SDA_HIGH;
    SCL_HIGH;
    Delay_us(10); // 总线空闲状态（高电平）
    SDA_LOW;      // SDA从高→低，产生Start
    Delay_us(10);
}
void simI2cSendByte(uint8_t byte)
{
    for (int i = 0; i < 8; i++)
    {
        SDA_LOW;      // 确保SDA线为低电平
        SCL_LOW;      // 确保SCL线为低电平
        Delay_us(10); // 确保SDA线稳定
        if (byte & 0x80)
        {
            SDA_HIGH; // 发送1
        }
        else
        {
            SDA_LOW; // 发送0
        }
        Delay_us(10);
        SCL_HIGH; // 拉高SCL线
        Delay_us(10);
        SCL_LOW;      // 拉低SCL线
        Delay_us(10); // 确保SCL线稳定
        byte <<= 1;   // 左移一位
    }
}
uint8_t simI2cwaitAck(void)
{
    SDA_HIGH; // 释放SDA线
    SCL_LOW;  // 确保SCL线为低电平
    Delay_us(10);
    SCL_HIGH; // 拉高SCL线，准备接收ACK
    Delay_us(10);
    uint8_t ack = NACK; // 默认NACK
    if (!SDA_READ)      // 检查SDA线状态
    {
        ack = ACK; // 如果SDA线为高电平，表示没有ACK
    }
    SCL_LOW; // 拉低SCL线，结束ACK接收
    Delay_us(10);
    return ack; // 返回ACK或NACK
}
void simI2cStop(void)
{
    SCL_HIGH; // 确保SCL线为高电平
    SDA_LOW;  // 准备Stop信号（SDA先低）
    Delay_us(10);
    SDA_HIGH; // SDA从低→高，产生Stop信号
    Delay_us(10);
}
/*
作爲主機被動響應
*/
void simI2cAck(void)
{
    SDA_HIGH;
    SCL_LOW;
    Delay_us(10);
    SDA_LOW;
    Delay_us(10);
    SCL_HIGH;
    Delay_us(10);
    SCL_LOW;
    Delay_us(10);
    SDA_HIGH;
    Delay_us(10);
}
uint8_t simI2cReadByte(void)
{
    uint8_t byte = 0;
    for (int i = 0; i < 8; i++)
    {
        SCL_LOW; // 确保SCL线为低电平
        Delay_us(10); // 确保SCL线稳定
        SCL_HIGH; // 拉高SCL线，准备读取数据
        Delay_us(10); // 等待数据稳定
        byte <<= 1; // 左移一位
        if (SDA_READ)
        {
            byte |= 0x01;
        }
        SCL_LOW;
        Delay_us(10);
    }
    return byte; // 返回读取的字节
}
void simI2cNack(void)
{
    SDA_HIGH; // 释放SDA线
    SCL_LOW;  // 确保SCL线为低电平
    Delay_us(10);
    SCL_HIGH; // 拉高SCL线，准备发送NACK
    Delay_us(10);
    SCL_LOW; // 拉低SCL线
    Delay_us(10);
}
void I2c_WriteByte(uint8_t innerAddr, uint8_t byte)
{
    simI2cStart();
    simI2cSendByte(HMC5883_ADDRESS << 1); // 发送设备地址（写操作）
    uint8_t ack = simI2cwaitAck(); // 等待ACK
    if(ack == ACK)
    {
        simI2cSendByte(innerAddr); // 发送寄存器地址
        simI2cwaitAck(); // 等待ACK
        simI2cSendByte(byte); // 发送数据字节
        simI2cwaitAck(); // 等待ACK
        simI2cStop(); // 发送Stop信号
    }
    else
    {
        printf("I2C Write Error: No ACK received.\r\n");
    }
    delay_ms(5);
}
uint8_t I2c_ReadByte(uint8_t innerAddr)
{
    simI2cStart();
    simI2cSendByte(HMC5883_ADDRESS << 1); // 发送设备地址（写操作）
	uint8_t ack = simI2cwaitAck();
    if(ack == NACK)
	{
		printf("I2C ACK ERROR");
		return 0x01;
	}		
    simI2cSendByte(innerAddr); // 发送寄存器地址
    ack = simI2cwaitAck(); // 等待ACK
	 if(ack == NACK)
	{
		printf("I2C ACK ERROR");
		return 0x01;
	}		
    simI2cStart(); // 重新发送Start信号
    simI2cSendByte((HMC5883_ADDRESS << 1) | 0x01); // 发送设备地址（读操作）
    ack = simI2cwaitAck(); // 等待ACK
		 if(ack == NACK)
	{
		printf("I2C ACK ERROR");
		return 0x01;
	}		
    uint8_t byte = simI2cReadByte(); // 读取数据字节
    simI2cNack(); // 发送NACK
    simI2cStop(); // 发送Stop信号
    return byte; // 返回读取的字节
}
void I2c_WriteBytes(uint8_t innerAddr,uint8_t *buf, uint8_t len)
{
    simI2cStart();
    simI2cSendByte(HMC5883_ADDRESS << 1); // 发送设备地址（写操作）
    uint8_t ack = simI2cwaitAck(); // 等待ACK
    if(ack == ACK)
    {
        simI2cSendByte(innerAddr); // 发送寄存器地址
        simI2cwaitAck(); // 等待ACK
        for (uint8_t i = 0; i < len; i++)
        {
            simI2cSendByte(buf[i]); // 发送数据字节
            simI2cwaitAck(); // 等待ACK
        }
        simI2cStop(); // 发送Stop信号
    }
    else
    {
        printf("I2C Write Error: No ACK received.\r\n");
    }
    delay_ms(5);
}
void I2c_ReadBytes(uint8_t innerAddr,uint8_t *buf, uint8_t len)
{
    simI2cStart();
    simI2cSendByte(HMC5883_ADDRESS << 1); // 发送设备地址（写操作）
    simI2cwaitAck(); // 等待ACK
    simI2cSendByte(innerAddr); // 发送寄存器地址
    simI2cwaitAck(); // 等待ACK
    simI2cStart(); // 重新发送Start信号
    simI2cSendByte((HMC5883_ADDRESS << 1) | 0x01); // 发送设备地址（读操作）
    simI2cwaitAck(); // 等待ACK
    for (uint8_t i = 0; i < len; i++)
    {
        buf[i] = simI2cReadByte(); // 读取数据字节
        if (i < len - 1)
        {
            simI2cAck(); // 发送ACK，除最后一个字节外
        }
        else
        {
            simI2cNack(); // 最后一个字节发送NACK
        }
    }
    simI2cStop(); // 发送Stop信号
}

